type op = 
    Add | Sub | Mult | Div | Mod 
    | And | Or | Eq | NEq | Less | LEq | Greater | GEq
   
type expr = 
    Id of string (* foo *)
    | Member of string * string (* foo.bar *)   
    | Integer of int (* 13 *)
    | Strings of string (* "helloworld" *)
    | GameType of string (* _HARD *)
    | Assign of expr * expr (* x = y *)
    | BinOp of expr * op * expr (* x + y *)
    | Not of expr (* !x *)
    | Call of string * expr list (* foo(x, y) *)
    | NoExpr (* for (;;) *)
    
type stmt = (* Statements *)
    Expr of expr (* foo = bar + 13; *)
    | Return of expr (* return 13; *)
    | Block of stmt list (* { ... } *)
    | If of expr * stmt * stmt (* if (foo == 13) {...} else {...} *)
    | For of expr * expr * expr * stmt (* for (i=0;i<10;i=i+1) { ... } *)
    | While of expr * stmt (* while (i<10) { ... } *)

type par_decl = {
    paramname : string; (* Variable Name*)
    paramtype : string; (* Variable Type *)
}

type var_decl = {
    varname : string; (* Variable Name *)
    vartype : string; (* Variable Type *)
}

type func_decl = {
    fname : string; (* Function Name*)
    rettype : string; (* Return Type *)
    formals : par_decl list; (* Argument Name *)
    locals : var_decl list; (* Local Variables *)
    body : stmt list;
}


(* types used for pacaml *)
type point = {
    mutable x : int;
    mutable y : int;  
}

type player = {
    mutable speed : int;
    mutable status : string;
    mutable p_point : point;
    mutable remaining_time : int;    
}

type item = {
    mutable i_type : int;
    mutable duration : int;
    mutable i_point : point;
    mutable color : float * float * float;
    mutable level : int;
}

type map = {
    mutable pacman : player;
    mutable list_item : item list;
    mutable width : int;
    mutable height : int;
}

type myType = Int of int | Bool of bool | String of string | Map of map | Player of player | Item of item | Point of point   
  

(* get the type of a variable *)
let getType v = 
    match v with
        Int(v) -> "int"
    | Bool(v) -> "bool"
    | String(v) -> "string"
    | Map(v) -> "map"
    | Player(v) -> "player"
    | Item(v) -> "item"
    | Point(v) -> "point"  

(* return  myType of a variable*)
let getInt v = 
    match v with
        Int(v) -> v
    | _ -> 0
        
let getBool v = 
    match v with
        Bool(v) -> v
    | Int(1) -> true    
    | _ -> false

let getString v = 
    match v with
        String(v) -> v
    | _ -> ""

let getMap v = 
    match v with
        Map(v) -> v
    | _ -> {pacman= {speed=0;  status="normal";  p_point={x=750; y=750};  remaining_time=0};list_item=[]; width=1500; height=1500}

let getPlayer v = 
    match v with
        Player(v) -> v
    | _ -> {speed=0;  status="normal"; p_point={x=750; y=750} ; remaining_time=0}
        
let getItem v = 
    match v with
        Item(v) -> v
    | _ -> {i_type=0; duration=0; i_point={x=0; y=0}; color=(1.,1.,1.) ; level=0}

let getPoint v = 
    match v with
        Point(v) -> v
    | _ -> {x=0; y=0}

type program = var_decl list * func_decl list (* global vars, funcs *)
